package com.property.manage.service.rent;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guardchina.framework.mybatis.model.CustomPage;
import com.guardchina.framework.util.exception.BusinessException;
import com.property.manage.dao.rent.RentMapper;
import com.property.manage.model.owner.OwnerEntity;
import com.property.manage.model.parking.ParkingRentDeductionEntity;
import com.property.manage.model.parking.ParkingRentEntity;
import com.property.manage.model.rent.*;
import com.property.manage.model.system.SysSet;
import com.property.manage.model.system.User;
import com.property.manage.service.flowingWater.HouseDepositService;
import com.property.manage.service.owner.OwnerService;
import com.property.manage.service.resource.BuildingService;
import com.property.manage.service.system.SnowflakeIdWorker;
import com.property.manage.service.system.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.security.SecureRandom;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class HouseRentService {
    @Autowired
    private OwnerService ownerService;
    @Autowired
    private RentMapper rentMapper;
    @Autowired
    private BuildingService buildingService;
    @Autowired
    private HouseRentDeductionService houseRentDeductionService;
    @Autowired
    private UserService userService;
    @Autowired
    private RentPaymentService rentPaymentService;
    @Autowired
    private HouseArrearsService houseArrearsService;

    @Autowired
    private RentService rentService;

    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;

    public OwnerEntity findOwner(Integer building) {
        return ownerService.findByBuilding(building);
    }

    @Transactional(rollbackFor = Exception.class)
    public void add(BigDecimal money, LocalDate startTime, LocalDate endTime, String name, String phone,
                    Integer buildingId, Integer villageId, BigDecimal propertyFee, BigDecimal otherFee,
                    String remarks, Integer userId
    ) {
        RentEntity entity = new RentEntity();
        entity.setBuildingId(buildingId);
        entity.setEndTime(endTime);
        entity.setPhone(phone);
        entity.setMoney(money);
        entity.setName(name);
        entity.setStartTime(startTime);
        entity.setVillageId(villageId);
        entity.setType(2);
        entity.setPropertyFee(propertyFee);
        entity.setOtherFee(otherFee);
        entity.setRemarks(remarks);
        entity.setTotalMoney(money.add(propertyFee).add(otherFee));
        entity.setState(RentEntity.STATE_RENTING);
        try {
            rentMapper.insert(entity);
        } catch (
                Exception e) {
            throw new BusinessException("新增房屋出租信息失败", String.format("新增房屋出租信息失败[%s]", e));
        }

    }


    public CustomPage<RentVo> page(Long pageNo, Long pageSize, Integer villageId, Integer building, Integer unit, String roomNumber) {
        Page<RentVo> page = new Page<>(pageNo, pageSize);
        IPage<RentVo> village = rentMapper.getHouseRentPage(page, villageId, building, unit, roomNumber);
        List<RentVo> records = village.getRecords();
        if (records.isEmpty()) {
            return new CustomPage<>(village);
        }
        for (RentVo record : records) {
            record.setNumber(buildingService.findAddress(record.getBuildingId()));
        }

        return new CustomPage<>(village);
    }

    @Transactional(rollbackFor = Exception.class)
    public void update(BigDecimal money, LocalDate startTime, LocalDate endTime, String name, String phone,
                       Integer buildingId, Integer villageId, BigDecimal propertyFee, BigDecimal otherFee,
                       String remarks, Integer userId, Integer id
    ) {
        UpdateWrapper<RentEntity> up = new UpdateWrapper<>();
        up.eq("id", id);
        up.set("money", money);
        up.set("start_time", startTime);
        up.set("end_time", endTime);
        up.set("name", name);
        up.set("phone", phone);
        up.set("building_id", buildingId);
        up.set("village_id", villageId);
        up.set("property_fee", propertyFee);
        up.set("other_fee", otherFee);
        up.set("total_money", money.add(propertyFee).add(otherFee));
        up.set("remarks", remarks);
        try {
            rentMapper.update(null, up);
        } catch (
                Exception e) {
            throw new BusinessException("修改房屋出租信息失败", String.format("新增房屋出租信息失败[%s]", e));
        }

    }

    public void delete(Integer id) {
        rentService.delete(id);
    }

    public List<RentEntity> findByVillageId(Integer villageId) {
        QueryWrapper<RentEntity> qw = new QueryWrapper<>();
        qw.eq("state", RentEntity.STATE_RENTING);
        qw.eq("village_id", villageId);
        return rentMapper.selectList(qw);
    }


    @Transactional(rollbackFor = Exception.class)
    public void deduction(Integer userId, Integer villageId, Integer year, Integer month) {

        log.info("userId[{}], villageId[{}], year[{}], month[{}]车位租金划扣", userId, villageId, year, month);
        Optional<HouseRentDeductionEntity> optional = houseRentDeductionService.find(villageId, year, month);
        optional.ifPresent(entity -> {
            throw new BusinessException(month + "月份已划扣，请勿重复划扣");
        });
        //增加划扣记录
        houseRentDeductionService.add(villageId, year, month);
        List<RentEntity> list = this.findByVillageId(villageId);
        if (list.isEmpty()) {
            log.info("{},该小区下无可划扣的数据", villageId);
            houseRentDeductionService.complete(villageId, year, month);
            return;
        }
        User user = userService.getUser(userId);
        String yearMonth = year + (month >= 10 ? month + "" : "0" + month);
        String remark = yearMonth + "房屋租金批量划扣";
        List<HouseArrearsEntity> arrears = new ArrayList<>();
        for (RentEntity rentEntity : list) {
            try {
                String billNo = snowflakeIdWorker.nextId() + "";
                rentPaymentService.add(user, rentEntity.getId(), villageId, rentEntity.getBuildingId(), 4, rentEntity.getMoney(), rentEntity.getPropertyFee(),
                        rentEntity.getOtherFee(), rentEntity.getTotalMoney(), rentEntity.getTotalMoney(), BigDecimal.ZERO, BigDecimal.ZERO, billNo, remark, rentEntity.getTotalMoney(), RentPaymentEntity.OTHER_TYPE_NORMAL);
            } catch (BusinessException e) {
                log.error("房屋租金划扣失败：rentId[{}], year[{}], month[{}]", rentEntity.getId(), year, month);
                HouseArrearsEntity houseArrearsEntity = getHouseArrearsEntity(rentEntity.getId(), villageId, year, month, rentEntity, "账户余额不足");
                arrears.add(houseArrearsEntity);

            } catch (Exception e) {
                log.error("房屋租金划扣失败：rentId[{}], year[{}], month[{}]", rentEntity.getId(), year, month);
                log.error("错误信息：", e);
                HouseArrearsEntity houseArrearsEntity = getHouseArrearsEntity(rentEntity.getId(), villageId, year, month, rentEntity, "操作失败");
                arrears.add(houseArrearsEntity);
            }
        }
        if (!arrears.isEmpty()) {
            houseArrearsService.add(arrears);
        }
        houseRentDeductionService.complete(villageId, year, month);
        log.info("房屋租金划扣完成");
    }

    public HouseArrearsEntity getHouseArrearsEntity(Integer rentId, Integer villageId, Integer year, Integer month, RentEntity rentEntity, String remark) {
        HouseArrearsEntity houseArrearsEntity = new HouseArrearsEntity();
        houseArrearsEntity.setBuildingId(rentEntity.getBuildingId());
        houseArrearsEntity.setCreateTime(LocalDate.now());
        houseArrearsEntity.setMoney(rentEntity.getMoney());
        houseArrearsEntity.setState(1);
        houseArrearsEntity.setOtherFee(rentEntity.getOtherFee());
        houseArrearsEntity.setPayName(buildingService.findAddress(rentEntity.getBuildingId()));
        houseArrearsEntity.setRemark(remark);
        houseArrearsEntity.setRentId(rentId);
        houseArrearsEntity.setVillageId(villageId);
        houseArrearsEntity.setPropertyFee(rentEntity.getPropertyFee());
        houseArrearsEntity.setTotalMoney(rentEntity.getTotalMoney());
        houseArrearsEntity.setTime(year + "-" + (month < 10 ? "0" + month : month));
        return houseArrearsEntity;
    }
}
